////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __WN_NETWORK_MANAGER_LINUX_H__
#define __WN_NETWORK_MANAGER_LINUX_H__

#include "WNNetworking/inc/WNNetworkManager.h"
#include "WNConcurrency/inc/WNSpinMutex.h"

#include <vector>

namespace WNConcurrency {
    class WNThread;
}

namespace WNNetworking {
    class WNLinuxConnection;
    class WNLinuxListenConnection;

    class WNNetworkManagerLinux : public WNNetworkManager {
    public:
        WNNetworkManagerLinux();
        virtual ~WNNetworkManagerLinux();

        virtual WNNetworkingError Initialize(WN_UINT32 _numWorkerThreads);
        virtual WNNetworkingError ConnectTo(WNConnection*& _outHandle, WNConnectionType _type, const WN_CHAR* _target, WN_UINT16 _port);
        virtual WNNetworkingError CreateListener(WNConnection*& _outHandle, WNConnectionType _type, WN_UINT16 _port, const WNConnectedCallback& _callback);
        virtual WN_VOID Cleanup();
        virtual WN_VOID DestroyConnection(WNConnection* _connection);
        
    private:
        enum eWNLinuxInitializationState {
            eWNNotStarted,
            eWNEPollWriteCreated,
            eWNWriteThreadsCreated,
            eWNEPollReadCreated,
            eWNReadThreadsCreated,
            eWNEPollListenCreated,
            eWNListenThreadCreated,
            eWNInitializationComplete
        };

        WN_BOOL AddToReadEPoll(WNLinuxConnection* _conn);
        WN_BOOL AddToWriteEPoll(WNLinuxConnection* _conn);
        WN_VOID CleanAllConnections();
        static WN_VOID WNReadThread(WNNetworkManagerLinux* _manager);
        static WN_VOID WNWriteThread(WNNetworkManagerLinux* _manager);
        static WN_VOID WNListenThread(WNNetworkManagerLinux* _manager);
        WNConcurrency::WNSpinMutex mListenMutex;
        WNConcurrency::WNSpinMutex mIncommingMutex;
        WNConcurrency::WNSpinMutex mOutgoingMutex;
        WNConcurrency::WNSpinMutex mInvalidMutex;

        eWNLinuxInitializationState mInitializationState;
        WN_INT32 mWriteEPollInstance;
        WN_INT32 mReadEPollInstance;
        WN_INT32 mListenEPollInstance;
        WNConcurrency::WNThread* mListenThread;
        WN_BOOL mShuttingDown;
        std::vector<WNConcurrency::WNThread*> mReadThreads;
        std::vector<WNConcurrency::WNThread*> mWriteThreads;
        std::list<WNLinuxListenConnection*> mListenConnections;
        std::list<WNConnection*> mInvalidConnections;
        std::list<WNLinuxConnection*> mIncommingConnections;
        std::list<WNLinuxConnection*> mOutgoingConnections;
    };
};

#endif//__WN_NETWORK_MANAGER_WINDOWS_H__
